/**
 * echarts组件：提示框
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 */


var Base = require('./base');
// 图形依赖
var CrossShape = require('../util/shape/Cross');
var LineShape = require('zrender/shape/Line');
var RectangleShape = require('zrender/shape/Rectangle');
var rectangleInstance = new RectangleShape({});
var ecConfig = require('../config');
// 提示框
ecConfig.tooltip = {
    zlevel: 1,
    // 一级层叠，频繁变化的tooltip指示器在pc上独立一层
    z: 8,
    // 二级层叠
    show: true,
    showContent: true,
    // tooltip主体内容
    trigger: 'item',
    // 触发类型，默认数据触发，见下图，可选为：'item' ¦ 'axis'
    // position: null          // 位置 {Array} | {Function}
    // formatter: null         // 内容格式器：{string}（Template） ¦ {Function}
    islandFormatter: '{a} <br/>{b} : {c}',
    // 数据孤岛内容格式器
    showDelay: 20,
    // 显示延迟，添加显示延迟可以避免频繁切换，单位ms
    hideDelay: 100,
    // 隐藏延迟，单位ms
    transitionDuration: 0.4,
    // 动画变换时间，单位s
    enterable: false,
    backgroundColor: 'rgba(0,0,0,0.7)',
    // 提示背景颜色，默认为透明度为0.7的黑色
    borderColor: '#333',
    // 提示边框颜色
    borderRadius: 4,
    // 提示边框圆角，单位px，默认为4
    borderWidth: 0,
    // 提示边框线宽，单位px，默认为0（无边框）
    padding: 5,
    // 提示内边距，单位px，默认各方向内边距为5，
    // 接受数组分别设定上右下左边距，同css
    axisPointer: {
        // 坐标轴指示器，坐标轴触发有效
        type: 'line',
        // 默认为直线，可选为：'line' | 'shadow' | 'cross'
        lineStyle: {
            // 直线指示器样式设置
            color: '#48b',
            width: 2,
            type: 'solid'
        },
        crossStyle: {
            color: '#1e90ff',
            width: 1,
            type: 'dashed'
        },
        shadowStyle: {
            // 阴影指示器样式设置
            color: 'rgba(150,150,150,0.3)',
            // 阴影颜色
            width: 'auto',
            // 阴影大小
            type: 'default'
        }
    },
    textStyle: { color: '#fff' }
};
var ecData = require('../util/ecData');
var zrConfig = require('zrender/config');
var zrEvent = require('zrender/tool/event');
var zrArea = require('zrender/tool/area');
var zrColor = require('zrender/tool/color');
var zrUtil = require('zrender/tool/util');
var zrShapeBase = require('zrender/shape/Base');
/**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} option 提示框参数
     * @param {HtmlElement} dom 目标对象
     * @param {ECharts} myChart 当前图表实例
     */
function Tooltip(ecTheme, messageCenter, zr, option, myChart) {
    Base.call(this, ecTheme, messageCenter, zr, option, myChart);
    this.dom = myChart.dom;
    var self = this;
    self._onmousemove = function (param) {
        return self.__onmousemove(param);
    };
    self._onglobalout = function (param) {
        return self.__onglobalout(param);
    };
    this.zr.on(zrConfig.EVENT.MOUSEMOVE, self._onmousemove);
    this.zr.on(zrConfig.EVENT.GLOBALOUT, self._onglobalout);
    self._hide = function (param) {
        return self.__hide(param);
    };
    self._tryShow = function (param) {
        return self.__tryShow(param);
    };
    self._refixed = function (param) {
        return self.__refixed(param);
    };
    self._setContent = function (ticket, res) {
        return self.__setContent(ticket, res);
    };
    this._tDom = this._tDom || document.createElement('div');
    // 避免拖拽时页面选中的尴尬
    this._tDom.onselectstart = function () {
        return false;
    };
    this._tDom.onmouseover = function () {
        self._mousein = true;
    };
    this._tDom.onmouseout = function () {
        self._mousein = false;
    };
    this._tDom.className = 'echarts-tooltip';
    this._tDom.style.position = 'absolute';
    // 不是多余的，别删！
    this.hasAppend = false;
    this._axisLineShape && this.zr.delShape(this._axisLineShape.id);
    this._axisLineShape = new LineShape({
        zlevel: this.getZlevelBase(),
        z: this.getZBase(),
        invisible: true,
        hoverable: false
    });
    this.shapeList.push(this._axisLineShape);
    this.zr.addShape(this._axisLineShape);
    this._axisShadowShape && this.zr.delShape(this._axisShadowShape.id);
    this._axisShadowShape = new LineShape({
        zlevel: this.getZlevelBase(),
        z: 1,
        // grid上，chart下
        invisible: true,
        hoverable: false
    });
    this.shapeList.push(this._axisShadowShape);
    this.zr.addShape(this._axisShadowShape);
    this._axisCrossShape && this.zr.delShape(this._axisCrossShape.id);
    this._axisCrossShape = new CrossShape({
        zlevel: this.getZlevelBase(),
        z: this.getZBase(),
        invisible: true,
        hoverable: false
    });
    this.shapeList.push(this._axisCrossShape);
    this.zr.addShape(this._axisCrossShape);
    this.showing = false;
    this.refresh(option);
}
Tooltip.prototype = {
    type: ecConfig.COMPONENT_TYPE_TOOLTIP,
    // 通用样式
    _gCssText: 'position:absolute;display:block;border-style:solid;white-space:nowrap;',
    /**
         * 根据配置设置dom样式
         */
    _style: function (opt) {
        if (!opt) {
            return '';
        }
        var cssText = [];
        if (opt.transitionDuration) {
            var transitionText = 'left ' + opt.transitionDuration + 's,' + 'top ' + opt.transitionDuration + 's';
            cssText.push('transition:' + transitionText);
            cssText.push('-moz-transition:' + transitionText);
            cssText.push('-webkit-transition:' + transitionText);
            cssText.push('-o-transition:' + transitionText);
        }
        if (opt.backgroundColor) {
            // for sb ie~
            cssText.push('background-Color:' + zrColor.toHex(opt.backgroundColor));
            cssText.push('filter:alpha(opacity=70)');
            cssText.push('background-Color:' + opt.backgroundColor);
        }
        if (opt.borderWidth != null) {
            cssText.push('border-width:' + opt.borderWidth + 'px');
        }
        if (opt.borderColor != null) {
            cssText.push('border-color:' + opt.borderColor);
        }
        if (opt.borderRadius != null) {
            cssText.push('border-radius:' + opt.borderRadius + 'px');
            cssText.push('-moz-border-radius:' + opt.borderRadius + 'px');
            cssText.push('-webkit-border-radius:' + opt.borderRadius + 'px');
            cssText.push('-o-border-radius:' + opt.borderRadius + 'px');
        }
        var textStyle = opt.textStyle;
        if (textStyle) {
            textStyle.color && cssText.push('color:' + textStyle.color);
            textStyle.decoration && cssText.push('text-decoration:' + textStyle.decoration);
            textStyle.align && cssText.push('text-align:' + textStyle.align);
            textStyle.fontFamily && cssText.push('font-family:' + textStyle.fontFamily);
            textStyle.fontSize && cssText.push('font-size:' + textStyle.fontSize + 'px');
            textStyle.fontSize && cssText.push('line-height:' + Math.round(textStyle.fontSize * 3 / 2) + 'px');
            textStyle.fontStyle && cssText.push('font-style:' + textStyle.fontStyle);
            textStyle.fontWeight && cssText.push('font-weight:' + textStyle.fontWeight);
        }
        var padding = opt.padding;
        if (padding != null) {
            padding = this.reformCssArray(padding);
            cssText.push('padding:' + padding[0] + 'px ' + padding[1] + 'px ' + padding[2] + 'px ' + padding[3] + 'px');
        }
        cssText = cssText.join(';') + ';';
        return cssText;
    },
    __hide: function () {
        this._lastDataIndex = -1;
        this._lastSeriesIndex = -1;
        this._lastItemTriggerId = -1;
        if (this._tDom) {
            this._tDom.style.display = 'none';
        }
        var needRefresh = false;
        if (!this._axisLineShape.invisible) {
            this._axisLineShape.invisible = true;
            this.zr.modShape(this._axisLineShape.id);
            needRefresh = true;
        }
        if (!this._axisShadowShape.invisible) {
            this._axisShadowShape.invisible = true;
            this.zr.modShape(this._axisShadowShape.id);
            needRefresh = true;
        }
        if (!this._axisCrossShape.invisible) {
            this._axisCrossShape.invisible = true;
            this.zr.modShape(this._axisCrossShape.id);
            needRefresh = true;
        }
        if (this._lastTipShape && this._lastTipShape.tipShape.length > 0) {
            this.zr.delShape(this._lastTipShape.tipShape);
            this._lastTipShape = false;
            this.shapeList.length = 2;
        }
        needRefresh && this.zr.refreshNextFrame();
        this.showing = false;
    },
    _show: function (position, x, y, specialCssText) {
        var domHeight = this._tDom.offsetHeight;
        var domWidth = this._tDom.offsetWidth;
        if (position) {
            if (typeof position === 'function') {
                position = position([
                    x,
                    y
                ]);
            }
            if (position instanceof Array) {
                x = position[0];
                y = position[1];
            }
        }
        if (x + domWidth > this._zrWidth) {
            // 太靠右
            //x = this._zrWidth - domWidth;
            x -= domWidth + 40;
        }
        if (y + domHeight > this._zrHeight) {
            // 太靠下
            //y = this._zrHeight - domHeight;
            y -= domHeight - 20;
        }
        if (y < 20) {
            y = 0;
        }
        this._tDom.style.cssText = this._gCssText + this._defaultCssText + (specialCssText ? specialCssText : '') + 'left:' + x + 'px;top:' + y + 'px;';
        if (domHeight < 10 || domWidth < 10) {
            // this._zrWidth - x < 100 || this._zrHeight - y < 100
            setTimeout(this._refixed, 20);
        }
        this.showing = true;
    },
    __refixed: function () {
        if (this._tDom) {
            var cssText = '';
            var domHeight = this._tDom.offsetHeight;
            var domWidth = this._tDom.offsetWidth;
            if (this._tDom.offsetLeft + domWidth > this._zrWidth) {
                cssText += 'left:' + (this._zrWidth - domWidth - 20) + 'px;';
            }
            if (this._tDom.offsetTop + domHeight > this._zrHeight) {
                cssText += 'top:' + (this._zrHeight - domHeight - 10) + 'px;';
            }
            if (cssText !== '') {
                this._tDom.style.cssText += cssText;
            }
        }
    },
    __tryShow: function () {
        var needShow;
        var trigger;
        if (!this._curTarget) {
            // 坐标轴事件
            this._findPolarTrigger() || this._findAxisTrigger();
        } else {
            // 数据项事件
            if (this._curTarget._type === 'island' && this.option.tooltip.show) {
                this._showItemTrigger();
                return;
            }
            var serie = ecData.get(this._curTarget, 'series');
            var data = ecData.get(this._curTarget, 'data');
            needShow = this.deepQuery([
                data,
                serie,
                this.option
            ], 'tooltip.show');
            if (serie == null || data == null || !needShow) {
                // 不响应tooltip的数据对象延时隐藏
                clearTimeout(this._hidingTicket);
                clearTimeout(this._showingTicket);
                this._hidingTicket = setTimeout(this._hide, this._hideDelay);
            } else {
                trigger = this.deepQuery([
                    data,
                    serie,
                    this.option
                ], 'tooltip.trigger');
                trigger === 'axis' ? this._showAxisTrigger(serie.xAxisIndex, serie.yAxisIndex, ecData.get(this._curTarget, 'dataIndex')) : this._showItemTrigger();
            }
        }
    },
    /**
         * 直角系 
         */
    _findAxisTrigger: function () {
        if (!this.component.xAxis || !this.component.yAxis) {
            this._hidingTicket = setTimeout(this._hide, this._hideDelay);
            return;
        }
        var series = this.option.series;
        var xAxisIndex;
        var yAxisIndex;
        for (var i = 0, l = series.length; i < l; i++) {
            // 找到第一个axis触发tooltip的系列
            if (this.deepQuery([
                    series[i],
                    this.option
                ], 'tooltip.trigger') === 'axis') {
                xAxisIndex = series[i].xAxisIndex || 0;
                yAxisIndex = series[i].yAxisIndex || 0;
                if (this.component.xAxis.getAxis(xAxisIndex) && this.component.xAxis.getAxis(xAxisIndex).type === ecConfig.COMPONENT_TYPE_AXIS_CATEGORY) {
                    // 横轴为类目轴
                    this._showAxisTrigger(xAxisIndex, yAxisIndex, this._getNearestDataIndex('x', this.component.xAxis.getAxis(xAxisIndex)));
                    return;
                } else if (this.component.yAxis.getAxis(yAxisIndex) && this.component.yAxis.getAxis(yAxisIndex).type === ecConfig.COMPONENT_TYPE_AXIS_CATEGORY) {
                    // 纵轴为类目轴
                    this._showAxisTrigger(xAxisIndex, yAxisIndex, this._getNearestDataIndex('y', this.component.yAxis.getAxis(yAxisIndex)));
                    return;
                } else {
                    // 双数值轴
                    this._showAxisTrigger(xAxisIndex, yAxisIndex, -1);
                    return;
                }
            }
        }
        if (this.option.tooltip.axisPointer.type === 'cross') {
            this._showAxisTrigger(-1, -1, -1);
        }
    },
    /**
         * 极坐标 
         */
    _findPolarTrigger: function () {
        if (!this.component.polar) {
            return false;
        }
        var x = zrEvent.getX(this._event);
        var y = zrEvent.getY(this._event);
        var polarIndex = this.component.polar.getNearestIndex([
            x,
            y
        ]);
        var valueIndex;
        if (polarIndex) {
            valueIndex = polarIndex.valueIndex;
            polarIndex = polarIndex.polarIndex;
        } else {
            polarIndex = -1;
        }
        if (polarIndex != -1) {
            return this._showPolarTrigger(polarIndex, valueIndex);
        }
        return false;
    },
    /**
         * 根据坐标轴事件带的属性获取最近的axisDataIndex
         */
    _getNearestDataIndex: function (direction, categoryAxis) {
        var dataIndex = -1;
        var x = zrEvent.getX(this._event);
        var y = zrEvent.getY(this._event);
        if (direction === 'x') {
            // 横轴为类目轴
            var left;
            var right;
            var xEnd = this.component.grid.getXend();
            var curCoord = categoryAxis.getCoordByIndex(dataIndex);
            while (curCoord < xEnd) {
                right = curCoord;
                if (curCoord <= x) {
                    left = curCoord;
                } else {
                    break;
                }
                curCoord = categoryAxis.getCoordByIndex(++dataIndex);
            }
            if (dataIndex <= 0) {
                dataIndex = 0;
            } else if (x - left <= right - x) {
                dataIndex -= 1;
            } else {
                // 离右边近，看是否为最后一个
                if (categoryAxis.getNameByIndex(dataIndex) == null) {
                    dataIndex -= 1;
                }
            }
            return dataIndex;
        } else {
            // 纵轴为类目轴
            var top;
            var bottom;
            var yStart = this.component.grid.getY();
            var curCoord = categoryAxis.getCoordByIndex(dataIndex);
            while (curCoord > yStart) {
                top = curCoord;
                if (curCoord >= y) {
                    bottom = curCoord;
                } else {
                    break;
                }
                curCoord = categoryAxis.getCoordByIndex(++dataIndex);
            }
            if (dataIndex <= 0) {
                dataIndex = 0;
            } else if (y - top >= bottom - y) {
                dataIndex -= 1;
            } else {
                // 离上方边近，看是否为最后一个
                if (categoryAxis.getNameByIndex(dataIndex) == null) {
                    dataIndex -= 1;
                }
            }
            return dataIndex;
        }
        return -1;
    },
    /**
         * 直角系 
         */
    _showAxisTrigger: function (xAxisIndex, yAxisIndex, dataIndex) {
        !this._event.connectTrigger && this.messageCenter.dispatch(ecConfig.EVENT.TOOLTIP_IN_GRID, this._event, null, this.myChart);
        if (this.component.xAxis == null || this.component.yAxis == null || xAxisIndex == null || yAxisIndex == null    // || dataIndex < 0
) {
            // 不响应tooltip的数据对象延时隐藏
            clearTimeout(this._hidingTicket);
            clearTimeout(this._showingTicket);
            this._hidingTicket = setTimeout(this._hide, this._hideDelay);
            return;
        }
        var series = this.option.series;
        var seriesArray = [];
        var seriesIndex = [];
        var categoryAxis;
        var formatter;
        var position;
        var showContent;
        var specialCssText = '';
        if (this.option.tooltip.trigger === 'axis') {
            if (!this.option.tooltip.show) {
                return;
            }
            formatter = this.option.tooltip.formatter;
            position = this.option.tooltip.position;
        }
        var axisLayout = xAxisIndex != -1 && this.component.xAxis.getAxis(xAxisIndex).type === ecConfig.COMPONENT_TYPE_AXIS_CATEGORY ? 'xAxis'    // 横轴为类目轴，找到所有用这条横轴并且axis触发的系列数据
 : yAxisIndex != -1 && this.component.yAxis.getAxis(yAxisIndex).type === ecConfig.COMPONENT_TYPE_AXIS_CATEGORY ? 'yAxis'    // 纵轴为类目轴，找到所有用这条纵轴并且axis触发的系列数据
 : false;
        var x;
        var y;
        if (axisLayout) {
            var axisIndex = axisLayout == 'xAxis' ? xAxisIndex : yAxisIndex;
            categoryAxis = this.component[axisLayout].getAxis(axisIndex);
            for (var i = 0, l = series.length; i < l; i++) {
                if (!this._isSelected(series[i].name)) {
                    continue;
                }
                if (series[i][axisLayout + 'Index'] === axisIndex && this.deepQuery([
                        series[i],
                        this.option
                    ], 'tooltip.trigger') === 'axis') {
                    showContent = this.query(series[i], 'tooltip.showContent') || showContent;
                    formatter = this.query(series[i], 'tooltip.formatter') || formatter;
                    position = this.query(series[i], 'tooltip.position') || position;
                    specialCssText += this._style(this.query(series[i], 'tooltip'));
                    if (series[i].stack != null && axisLayout == 'xAxis') {
                        seriesArray.unshift(series[i]);
                        seriesIndex.unshift(i);
                    } else {
                        seriesArray.push(series[i]);
                        seriesIndex.push(i);
                    }
                }
            }
            // 寻找高亮元素
            this.messageCenter.dispatch(ecConfig.EVENT.TOOLTIP_HOVER, this._event, {
                seriesIndex: seriesIndex,
                dataIndex: dataIndex
            }, this.myChart);
            var rect;
            if (axisLayout == 'xAxis') {
                x = this.subPixelOptimize(categoryAxis.getCoordByIndex(dataIndex), this._axisLineWidth);
                y = zrEvent.getY(this._event);
                rect = [
                    x,
                    this.component.grid.getY(),
                    x,
                    this.component.grid.getYend()
                ];
            } else {
                x = zrEvent.getX(this._event);
                y = this.subPixelOptimize(categoryAxis.getCoordByIndex(dataIndex), this._axisLineWidth);
                rect = [
                    this.component.grid.getX(),
                    y,
                    this.component.grid.getXend(),
                    y
                ];
            }
            this._styleAxisPointer(seriesArray, rect[0], rect[1], rect[2], rect[3], categoryAxis.getGap(), x, y);
        } else {
            // 双数值轴
            x = zrEvent.getX(this._event);
            y = zrEvent.getY(this._event);
            this._styleAxisPointer(series, this.component.grid.getX(), y, this.component.grid.getXend(), y, 0, x, y);
            if (dataIndex >= 0) {
                this._showItemTrigger(true);
            } else {
                clearTimeout(this._hidingTicket);
                clearTimeout(this._showingTicket);
                this._tDom.style.display = 'none';
            }
        }
        if (seriesArray.length > 0) {
            // 复位item trigger和axis trigger间短距离来回变换时的不响应
            this._lastItemTriggerId = -1;
            // 相同dataIndex seriesIndex时不再触发内容更新
            if (this._lastDataIndex != dataIndex || this._lastSeriesIndex != seriesIndex[0]) {
                this._lastDataIndex = dataIndex;
                this._lastSeriesIndex = seriesIndex[0];
                var data;
                var value;
                if (typeof formatter === 'function') {
                    var params = [];
                    for (var i = 0, l = seriesArray.length; i < l; i++) {
                        data = seriesArray[i].data[dataIndex];
                        value = this.getDataFromOption(data, '-');
                        params.push({
                            seriesIndex: seriesIndex[i],
                            seriesName: seriesArray[i].name || '',
                            series: seriesArray[i],
                            dataIndex: dataIndex,
                            data: data,
                            name: categoryAxis.getNameByIndex(dataIndex),
                            value: value,
                            // 向下兼容
                            0: seriesArray[i].name || '',
                            1: categoryAxis.getNameByIndex(dataIndex),
                            2: value,
                            3: data
                        });
                    }
                    this._curTicket = 'axis:' + dataIndex;
                    this._tDom.innerHTML = formatter.call(this.myChart, params, this._curTicket, this._setContent);
                } else if (typeof formatter === 'string') {
                    this._curTicket = NaN;
                    formatter = formatter.replace('{a}', '{a0}').replace('{b}', '{b0}').replace('{c}', '{c0}');
                    for (var i = 0, l = seriesArray.length; i < l; i++) {
                        formatter = formatter.replace('{a' + i + '}', this._encodeHTML(seriesArray[i].name || ''));
                        formatter = formatter.replace('{b' + i + '}', this._encodeHTML(categoryAxis.getNameByIndex(dataIndex)));
                        data = seriesArray[i].data[dataIndex];
                        data = this.getDataFromOption(data, '-');
                        formatter = formatter.replace('{c' + i + '}', data instanceof Array ? data : this.numAddCommas(data));
                    }
                    this._tDom.innerHTML = formatter;
                } else {
                    this._curTicket = NaN;
                    formatter = this._encodeHTML(categoryAxis.getNameByIndex(dataIndex));
                    for (var i = 0, l = seriesArray.length; i < l; i++) {
                        formatter += '<br/>' + this._encodeHTML(seriesArray[i].name || '') + ' : ';
                        data = seriesArray[i].data[dataIndex];
                        data = this.getDataFromOption(data, '-');
                        formatter += data instanceof Array ? data : this.numAddCommas(data);
                    }
                    this._tDom.innerHTML = formatter;
                }
            }
            // don't modify, just false, showContent == undefined == true
            if (showContent === false || !this.option.tooltip.showContent) {
                // 只用tooltip的行为，不显示主体
                return;
            }
            if (!this.hasAppend) {
                this._tDom.style.left = this._zrWidth / 2 + 'px';
                this._tDom.style.top = this._zrHeight / 2 + 'px';
                this.dom.firstChild.appendChild(this._tDom);
                this.hasAppend = true;
            }
            this._show(position, x + 10, y + 10, specialCssText);
        }
    },
    /**
         * 极坐标 
         */
    _showPolarTrigger: function (polarIndex, dataIndex) {
        if (this.component.polar == null || polarIndex == null || dataIndex == null || dataIndex < 0) {
            return false;
        }
        var series = this.option.series;
        var seriesArray = [];
        var seriesIndex = [];
        var formatter;
        var position;
        var showContent;
        var specialCssText = '';
        if (this.option.tooltip.trigger === 'axis') {
            if (!this.option.tooltip.show) {
                return false;
            }
            formatter = this.option.tooltip.formatter;
            position = this.option.tooltip.position;
        }
        var indicatorName = this.option.polar[polarIndex].indicator[dataIndex].text;
        // 找到所有用这个极坐标并且axis触发的系列数据
        for (var i = 0, l = series.length; i < l; i++) {
            if (!this._isSelected(series[i].name)) {
                continue;
            }
            if (series[i].polarIndex === polarIndex && this.deepQuery([
                    series[i],
                    this.option
                ], 'tooltip.trigger') === 'axis') {
                showContent = this.query(series[i], 'tooltip.showContent') || showContent;
                formatter = this.query(series[i], 'tooltip.formatter') || formatter;
                position = this.query(series[i], 'tooltip.position') || position;
                specialCssText += this._style(this.query(series[i], 'tooltip'));
                seriesArray.push(series[i]);
                seriesIndex.push(i);
            }
        }
        if (seriesArray.length > 0) {
            var polarData;
            var data;
            var value;
            var params = [];
            for (var i = 0, l = seriesArray.length; i < l; i++) {
                polarData = seriesArray[i].data;
                for (var j = 0, k = polarData.length; j < k; j++) {
                    data = polarData[j];
                    if (!this._isSelected(data.name)) {
                        continue;
                    }
                    data = data != null ? data : {
                        name: '',
                        value: { dataIndex: '-' }
                    };
                    value = this.getDataFromOption(data.value[dataIndex]);
                    params.push({
                        seriesIndex: seriesIndex[i],
                        seriesName: seriesArray[i].name || '',
                        series: seriesArray[i],
                        dataIndex: dataIndex,
                        data: data,
                        name: data.name,
                        indicator: indicatorName,
                        value: value,
                        // 向下兼容
                        0: seriesArray[i].name || '',
                        1: data.name,
                        2: value,
                        3: indicatorName
                    });
                }
            }
            if (params.length <= 0) {
                return;
            }
            // 复位item trigger和axis trigger间短距离来回变换时的不响应
            this._lastItemTriggerId = -1;
            // 相同dataIndex seriesIndex时不再触发内容更新
            if (this._lastDataIndex != dataIndex || this._lastSeriesIndex != seriesIndex[0]) {
                this._lastDataIndex = dataIndex;
                this._lastSeriesIndex = seriesIndex[0];
                if (typeof formatter === 'function') {
                    this._curTicket = 'axis:' + dataIndex;
                    this._tDom.innerHTML = formatter.call(this.myChart, params, this._curTicket, this._setContent);
                } else if (typeof formatter === 'string') {
                    formatter = formatter.replace('{a}', '{a0}').replace('{b}', '{b0}').replace('{c}', '{c0}').replace('{d}', '{d0}');
                    for (var i = 0, l = params.length; i < l; i++) {
                        formatter = formatter.replace('{a' + i + '}', this._encodeHTML(params[i].seriesName));
                        formatter = formatter.replace('{b' + i + '}', this._encodeHTML(params[i].name));
                        formatter = formatter.replace('{c' + i + '}', this.numAddCommas(params[i].value));
                        formatter = formatter.replace('{d' + i + '}', this._encodeHTML(params[i].indicator));
                    }
                    this._tDom.innerHTML = formatter;
                } else {
                    formatter = this._encodeHTML(params[0].name) + '<br/>' + this._encodeHTML(params[0].indicator) + ' : ' + this.numAddCommas(params[0].value);
                    for (var i = 1, l = params.length; i < l; i++) {
                        formatter += '<br/>' + this._encodeHTML(params[i].name) + '<br/>';
                        formatter += this._encodeHTML(params[i].indicator) + ' : ' + this.numAddCommas(params[i].value);
                    }
                    this._tDom.innerHTML = formatter;
                }
            }
            // don't modify, just false, showContent == undefined == true
            if (showContent === false || !this.option.tooltip.showContent) {
                // 只用tooltip的行为，不显示主体
                return;
            }
            if (!this.hasAppend) {
                this._tDom.style.left = this._zrWidth / 2 + 'px';
                this._tDom.style.top = this._zrHeight / 2 + 'px';
                this.dom.firstChild.appendChild(this._tDom);
                this.hasAppend = true;
            }
            this._show(position, zrEvent.getX(this._event), zrEvent.getY(this._event), specialCssText);
            return true;
        }
    },
    /**
         * @parma {boolean} axisTrigger 
         */
    _showItemTrigger: function (axisTrigger) {
        if (!this._curTarget) {
            return;
        }
        var serie = ecData.get(this._curTarget, 'series');
        var seriesIndex = ecData.get(this._curTarget, 'seriesIndex');
        var data = ecData.get(this._curTarget, 'data');
        var dataIndex = ecData.get(this._curTarget, 'dataIndex');
        var name = ecData.get(this._curTarget, 'name');
        var value = ecData.get(this._curTarget, 'value');
        var special = ecData.get(this._curTarget, 'special');
        var special2 = ecData.get(this._curTarget, 'special2');
        var queryTarget = [
            data,
            serie,
            this.option
        ];
        // 从低优先级往上找到trigger为item的formatter和样式
        var formatter;
        var position;
        var showContent;
        var specialCssText = '';
        if (this._curTarget._type != 'island') {
            // 全局
            var trigger = axisTrigger ? 'axis' : 'item';
            if (this.option.tooltip.trigger === trigger) {
                formatter = this.option.tooltip.formatter;
                position = this.option.tooltip.position;
            }
            // 系列
            if (this.query(serie, 'tooltip.trigger') === trigger) {
                showContent = this.query(serie, 'tooltip.showContent') || showContent;
                formatter = this.query(serie, 'tooltip.formatter') || formatter;
                position = this.query(serie, 'tooltip.position') || position;
                specialCssText += this._style(this.query(serie, 'tooltip'));
            }
            // 数据项
            showContent = this.query(data, 'tooltip.showContent') || showContent;
            formatter = this.query(data, 'tooltip.formatter') || formatter;
            position = this.query(data, 'tooltip.position') || position;
            specialCssText += this._style(this.query(data, 'tooltip'));
        } else {
            this._lastItemTriggerId = NaN;
            showContent = this.deepQuery(queryTarget, 'tooltip.showContent');
            formatter = this.deepQuery(queryTarget, 'tooltip.islandFormatter');
            position = this.deepQuery(queryTarget, 'tooltip.islandPosition');
        }
        // 复位item trigger和axis trigger间短距离来回变换时的不响应
        this._lastDataIndex = -1;
        this._lastSeriesIndex = -1;
        // 相同dataIndex seriesIndex时不再触发内容更新
        if (this._lastItemTriggerId !== this._curTarget.id) {
            this._lastItemTriggerId = this._curTarget.id;
            if (typeof formatter === 'function') {
                this._curTicket = (serie.name || '') + ':' + dataIndex;
                this._tDom.innerHTML = formatter.call(this.myChart, {
                    seriesIndex: seriesIndex,
                    seriesName: serie.name || '',
                    series: serie,
                    dataIndex: dataIndex,
                    data: data,
                    name: name,
                    value: value,
                    percent: special,
                    // 饼图
                    indicator: special,
                    // 雷达图
                    value2: special2,
                    indicator2: special2,
                    // 向下兼容
                    0: serie.name || '',
                    1: name,
                    2: value,
                    3: special,
                    4: special2,
                    5: data,
                    6: seriesIndex,
                    7: dataIndex
                }, this._curTicket, this._setContent);
            } else if (typeof formatter === 'string') {
                this._curTicket = NaN;
                formatter = formatter.replace('{a}', '{a0}').replace('{b}', '{b0}').replace('{c}', '{c0}');
                formatter = formatter.replace('{a0}', this._encodeHTML(serie.name || '')).replace('{b0}', this._encodeHTML(name)).replace('{c0}', value instanceof Array ? value : this.numAddCommas(value));
                formatter = formatter.replace('{d}', '{d0}').replace('{d0}', special || '');
                formatter = formatter.replace('{e}', '{e0}').replace('{e0}', ecData.get(this._curTarget, 'special2') || '');
                this._tDom.innerHTML = formatter;
            } else {
                this._curTicket = NaN;
                if (serie.type === ecConfig.CHART_TYPE_RADAR && special) {
                    this._tDom.innerHTML = this._itemFormatter.radar.call(this, serie, name, value, special);
                }    // chord 处理暂时跟 force 一样
                     // else if (serie.type === ecConfig.CHART_TYPE_CHORD) {
                     //     this._tDom.innerHTML = this._itemFormatter.chord.call(
                     //         this, serie, name, value, special, special2
                     //     );
                     // }
                else if (serie.type === ecConfig.CHART_TYPE_EVENTRIVER) {
                    this._tDom.innerHTML = this._itemFormatter.eventRiver.call(this, serie, name, value, data);
                } else {
                    this._tDom.innerHTML = '' + (serie.name != null ? this._encodeHTML(serie.name) + '<br/>' : '') + (name === '' ? '' : this._encodeHTML(name) + ' : ') + (value instanceof Array ? value : this.numAddCommas(value));
                }
            }
        }
        var x = zrEvent.getX(this._event);
        var y = zrEvent.getY(this._event);
        if (this.deepQuery(queryTarget, 'tooltip.axisPointer.show') && this.component.grid) {
            this._styleAxisPointer([serie], this.component.grid.getX(), y, this.component.grid.getXend(), y, 0, x, y);
        } else {
            this._hide();
        }
        // don't modify, just false, showContent == undefined == true
        if (showContent === false || !this.option.tooltip.showContent) {
            // 只用tooltip的行为，不显示主体
            return;
        }
        if (!this.hasAppend) {
            this._tDom.style.left = this._zrWidth / 2 + 'px';
            this._tDom.style.top = this._zrHeight / 2 + 'px';
            this.dom.firstChild.appendChild(this._tDom);
            this.hasAppend = true;
        }
        this._show(position, x + 20, y - 20, specialCssText);
    },
    _itemFormatter: {
        radar: function (serie, name, value, indicator) {
            var html = '';
            html += this._encodeHTML(name === '' ? serie.name || '' : name);
            html += html === '' ? '' : '<br />';
            for (var i = 0; i < indicator.length; i++) {
                html += this._encodeHTML(indicator[i].text) + ' : ' + this.numAddCommas(value[i]) + '<br />';
            }
            return html;
        },
        chord: function (serie, name, value, special, special2) {
            if (special2 == null) {
                // 外环上
                return this._encodeHTML(name) + ' (' + this.numAddCommas(value) + ')';
            } else {
                var name1 = this._encodeHTML(name);
                var name2 = this._encodeHTML(special);
                // 内部弦上
                return '' + (serie.name != null ? this._encodeHTML(serie.name) + '<br/>' : '') + name1 + ' -> ' + name2 + ' (' + this.numAddCommas(value) + ')' + '<br />' + name2 + ' -> ' + name1 + ' (' + this.numAddCommas(special2) + ')';
            }
        },
        eventRiver: function (serie, name, value, data) {
            var html = '';
            html += this._encodeHTML(serie.name === '' ? '' : serie.name + ' : ');
            html += this._encodeHTML(name);
            html += html === '' ? '' : '<br />';
            data = data.evolution;
            for (var i = 0, l = data.length; i < l; i++) {
                html += '<div style="padding-top:5px;">';
                if (!data[i].detail) {
                    continue;
                }
                if (data[i].detail.img) {
                    html += '<img src="' + data[i].detail.img + '" style="float:left;width:40px;height:40px;">';
                }
                html += '<div style="margin-left:45px;">' + data[i].time + '<br/>';
                html += '<a href="' + data[i].detail.link + '" target="_blank">';
                html += data[i].detail.text + '</a></div>';
                html += '</div>';
            }
            return html;
        }
    },
    /**
         * 设置坐标轴指示器样式 
         */
    _styleAxisPointer: function (seriesArray, xStart, yStart, xEnd, yEnd, gap, x, y) {
        if (seriesArray.length > 0) {
            var queryTarget;
            var curType;
            var axisPointer = this.option.tooltip.axisPointer;
            var pointType = axisPointer.type;
            var style = {
                line: {},
                cross: {},
                shadow: {}
            };
            for (var pType in style) {
                style[pType].color = axisPointer[pType + 'Style'].color;
                style[pType].width = axisPointer[pType + 'Style'].width;
                style[pType].type = axisPointer[pType + 'Style'].type;
            }
            for (var i = 0, l = seriesArray.length; i < l; i++) {
                //if (this.deepQuery([seriesArray[i], this.option], 'tooltip.trigger') === 'axis') {
                queryTarget = seriesArray[i];
                curType = this.query(queryTarget, 'tooltip.axisPointer.type');
                pointType = curType || pointType;
                if (curType) {
                    style[curType].color = this.query(queryTarget, 'tooltip.axisPointer.' + curType + 'Style.color') || style[curType].color;
                    style[curType].width = this.query(queryTarget, 'tooltip.axisPointer.' + curType + 'Style.width') || style[curType].width;
                    style[curType].type = this.query(queryTarget, 'tooltip.axisPointer.' + curType + 'Style.type') || style[curType].type;
                }    //}
            }
            if (pointType === 'line') {
                var lineWidth = style.line.width;
                var isVertical = xStart == xEnd;
                this._axisLineShape.style = {
                    xStart: isVertical ? this.subPixelOptimize(xStart, lineWidth) : xStart,
                    yStart: isVertical ? yStart : this.subPixelOptimize(yStart, lineWidth),
                    xEnd: isVertical ? this.subPixelOptimize(xEnd, lineWidth) : xEnd,
                    yEnd: isVertical ? yEnd : this.subPixelOptimize(yEnd, lineWidth),
                    strokeColor: style.line.color,
                    lineWidth: lineWidth,
                    lineType: style.line.type
                };
                this._axisLineShape.invisible = false;
                this.zr.modShape(this._axisLineShape.id);
            } else if (pointType === 'cross') {
                var crossWidth = style.cross.width;
                this._axisCrossShape.style = {
                    brushType: 'stroke',
                    rect: this.component.grid.getArea(),
                    x: this.subPixelOptimize(x, crossWidth),
                    y: this.subPixelOptimize(y, crossWidth),
                    text: ('( ' + this.component.xAxis.getAxis(0).getValueFromCoord(x) + ' , ' + this.component.yAxis.getAxis(0).getValueFromCoord(y) + ' )').replace('  , ', ' ').replace(' ,  ', ' '),
                    textPosition: 'specific',
                    strokeColor: style.cross.color,
                    lineWidth: crossWidth,
                    lineType: style.cross.type
                };
                if (this.component.grid.getXend() - x > 100) {
                    // 右侧有空间
                    this._axisCrossShape.style.textAlign = 'left';
                    this._axisCrossShape.style.textX = x + 10;
                } else {
                    this._axisCrossShape.style.textAlign = 'right';
                    this._axisCrossShape.style.textX = x - 10;
                }
                if (y - this.component.grid.getY() > 50) {
                    // 上方有空间
                    this._axisCrossShape.style.textBaseline = 'bottom';
                    this._axisCrossShape.style.textY = y - 10;
                } else {
                    this._axisCrossShape.style.textBaseline = 'top';
                    this._axisCrossShape.style.textY = y + 10;
                }
                this._axisCrossShape.invisible = false;
                this.zr.modShape(this._axisCrossShape.id);
            } else if (pointType === 'shadow') {
                if (style.shadow.width == null || style.shadow.width === 'auto' || isNaN(style.shadow.width)) {
                    style.shadow.width = gap;
                }
                if (xStart === xEnd) {
                    // 纵向
                    if (Math.abs(this.component.grid.getX() - xStart) < 2) {
                        // 最左边
                        style.shadow.width /= 2;
                        xStart = xEnd = xEnd + style.shadow.width / 2;
                    } else if (Math.abs(this.component.grid.getXend() - xStart) < 2) {
                        // 最右边
                        style.shadow.width /= 2;
                        xStart = xEnd = xEnd - style.shadow.width / 2;
                    }
                } else if (yStart === yEnd) {
                    // 横向
                    if (Math.abs(this.component.grid.getY() - yStart) < 2) {
                        // 最上边
                        style.shadow.width /= 2;
                        yStart = yEnd = yEnd + style.shadow.width / 2;
                    } else if (Math.abs(this.component.grid.getYend() - yStart) < 2) {
                        // 最右边
                        style.shadow.width /= 2;
                        yStart = yEnd = yEnd - style.shadow.width / 2;
                    }
                }
                this._axisShadowShape.style = {
                    xStart: xStart,
                    yStart: yStart,
                    xEnd: xEnd,
                    yEnd: yEnd,
                    strokeColor: style.shadow.color,
                    lineWidth: style.shadow.width
                };
                this._axisShadowShape.invisible = false;
                this.zr.modShape(this._axisShadowShape.id);
            }
            this.zr.refreshNextFrame();
        }
    },
    __onmousemove: function (param) {
        clearTimeout(this._hidingTicket);
        clearTimeout(this._showingTicket);
        if (this._mousein && this._enterable) {
            return;
        }
        var target = param.target;
        var mx = zrEvent.getX(param.event);
        var my = zrEvent.getY(param.event);
        if (!target) {
            // 判断是否落到直角系里，axis触发的tooltip
            this._curTarget = false;
            this._event = param.event;
            // this._event._target = this._event.target || this._event.toElement;
            this._event.zrenderX = mx;
            this._event.zrenderY = my;
            if (this._needAxisTrigger && this.component.grid && zrArea.isInside(rectangleInstance, this.component.grid.getArea(), mx, my)) {
                this._showingTicket = setTimeout(this._tryShow, this._showDelay);
            } else if (this._needAxisTrigger && this.component.polar && this.component.polar.isInside([
                    mx,
                    my
                ]) != -1) {
                this._showingTicket = setTimeout(this._tryShow, this._showDelay);
            } else {
                !this._event.connectTrigger && this.messageCenter.dispatch(ecConfig.EVENT.TOOLTIP_OUT_GRID, this._event, null, this.myChart);
                this._hidingTicket = setTimeout(this._hide, this._hideDelay);
            }
        } else {
            this._curTarget = target;
            this._event = param.event;
            // this._event._target = this._event.target || this._event.toElement;
            this._event.zrenderX = mx;
            this._event.zrenderY = my;
            var polarIndex;
            if (this._needAxisTrigger && this.component.polar && (polarIndex = this.component.polar.isInside([
                    mx,
                    my
                ])) != -1) {
                // 看用这个polar的系列数据是否是axis触发，如果是设置_curTarget为nul
                var series = this.option.series;
                for (var i = 0, l = series.length; i < l; i++) {
                    if (series[i].polarIndex === polarIndex && this.deepQuery([
                            series[i],
                            this.option
                        ], 'tooltip.trigger') === 'axis') {
                        this._curTarget = null;
                        break;
                    }
                }
            }
            this._showingTicket = setTimeout(this._tryShow, this._showDelay);
        }
    },
    /**
         * zrender事件响应：鼠标离开绘图区域
         */
    __onglobalout: function () {
        clearTimeout(this._hidingTicket);
        clearTimeout(this._showingTicket);
        this._hidingTicket = setTimeout(this._hide, this._hideDelay);
    },
    /**
         * 异步回调填充内容
         */
    __setContent: function (ticket, content) {
        if (!this._tDom) {
            return;
        }
        if (ticket === this._curTicket) {
            this._tDom.innerHTML = content;
        }
        setTimeout(this._refixed, 20);
    },
    ontooltipHover: function (param, tipShape) {
        if (!this._lastTipShape || this._lastTipShape && this._lastTipShape.dataIndex != param.dataIndex) {
            if (this._lastTipShape && this._lastTipShape.tipShape.length > 0) {
                this.zr.delShape(this._lastTipShape.tipShape);
                this.shapeList.length = 2;
            }
            for (var i = 0, l = tipShape.length; i < l; i++) {
                tipShape[i].zlevel = this.getZlevelBase();
                tipShape[i].z = this.getZBase();
                tipShape[i].style = zrShapeBase.prototype.getHighlightStyle(tipShape[i].style, tipShape[i].highlightStyle);
                tipShape[i].draggable = false;
                tipShape[i].hoverable = false;
                tipShape[i].clickable = false;
                tipShape[i].ondragend = null;
                tipShape[i].ondragover = null;
                tipShape[i].ondrop = null;
                this.shapeList.push(tipShape[i]);
                this.zr.addShape(tipShape[i]);
            }
            this._lastTipShape = {
                dataIndex: param.dataIndex,
                tipShape: tipShape
            };
        }
    },
    ondragend: function () {
        this._hide();
    },
    /**
         * 图例选择
         */
    onlegendSelected: function (param) {
        this._selectedMap = param.selected;
    },
    _setSelectedMap: function () {
        if (this.component.legend) {
            this._selectedMap = zrUtil.clone(this.component.legend.getSelectedMap());
        } else {
            this._selectedMap = {};
        }
    },
    _isSelected: function (itemName) {
        if (this._selectedMap[itemName] != null) {
            return this._selectedMap[itemName];
        } else {
            return true;    // 没在legend里定义的都为true啊~
        }
    },
    /**
         * 模拟tooltip hover方法
         * {object} params  参数
         *          {seriesIndex: 0, seriesName:'', dataInex:0} line、bar、scatter、k、radar
         *          {seriesIndex: 0, seriesName:'', name:''} map、pie、chord
         */
    showTip: function (params) {
        if (!params) {
            return;
        }
        var seriesIndex;
        var series = this.option.series;
        if (params.seriesIndex != null) {
            seriesIndex = params.seriesIndex;
        } else {
            var seriesName = params.seriesName;
            for (var i = 0, l = series.length; i < l; i++) {
                if (series[i].name === seriesName) {
                    seriesIndex = i;
                    break;
                }
            }
        }
        var serie = series[seriesIndex];
        if (serie == null) {
            return;
        }
        var chart = this.myChart.chart[serie.type];
        var isAxisTrigger = this.deepQuery([
            serie,
            this.option
        ], 'tooltip.trigger') === 'axis';
        if (!chart) {
            return;
        }
        if (isAxisTrigger) {
            // axis trigger
            var dataIndex = params.dataIndex;
            switch (chart.type) {
            case ecConfig.CHART_TYPE_LINE:
            case ecConfig.CHART_TYPE_BAR:
            case ecConfig.CHART_TYPE_K:
            case ecConfig.CHART_TYPE_RADAR:
                if (this.component.polar == null || serie.data[0].value.length <= dataIndex) {
                    return;
                }
                var polarIndex = serie.polarIndex || 0;
                var vector = this.component.polar.getVector(polarIndex, dataIndex, 'max');
                this._event = {
                    zrenderX: vector[0],
                    zrenderY: vector[1]
                };
                this._showPolarTrigger(polarIndex, dataIndex);
                break;
            }
        } else {
            // item trigger
            var shapeList = chart.shapeList;
            var x;
            var y;
            switch (chart.type) {
            case ecConfig.CHART_TYPE_LINE:
            case ecConfig.CHART_TYPE_BAR:
            case ecConfig.CHART_TYPE_K:
            case ecConfig.CHART_TYPE_TREEMAP:
            case ecConfig.CHART_TYPE_SCATTER:
                var dataIndex = params.dataIndex;
                for (var i = 0, l = shapeList.length; i < l; i++) {
                    if (shapeList[i]._mark == null && ecData.get(shapeList[i], 'seriesIndex') == seriesIndex && ecData.get(shapeList[i], 'dataIndex') == dataIndex) {
                        this._curTarget = shapeList[i];
                        x = shapeList[i].style.x;
                        y = chart.type != ecConfig.CHART_TYPE_K ? shapeList[i].style.y : shapeList[i].style.y[0];
                        break;
                    }
                }
                break;
            case ecConfig.CHART_TYPE_RADAR:
                var dataIndex = params.dataIndex;
                for (var i = 0, l = shapeList.length; i < l; i++) {
                    if (shapeList[i].type === 'polygon' && ecData.get(shapeList[i], 'seriesIndex') == seriesIndex && ecData.get(shapeList[i], 'dataIndex') == dataIndex) {
                        this._curTarget = shapeList[i];
                        var vector = this.component.polar.getCenter(serie.polarIndex || 0);
                        x = vector[0];
                        y = vector[1];
                        break;
                    }
                }
                break;
            case ecConfig.CHART_TYPE_PIE:
                var name = params.name;
                for (var i = 0, l = shapeList.length; i < l; i++) {
                    if (shapeList[i].type === 'sector' && ecData.get(shapeList[i], 'seriesIndex') == seriesIndex && ecData.get(shapeList[i], 'name') == name) {
                        this._curTarget = shapeList[i];
                        var style = this._curTarget.style;
                        var midAngle = (style.startAngle + style.endAngle) / 2 * Math.PI / 180;
                        x = this._curTarget.style.x + Math.cos(midAngle) * style.r / 1.5;
                        y = this._curTarget.style.y - Math.sin(midAngle) * style.r / 1.5;
                        break;
                    }
                }
                break;
            case ecConfig.CHART_TYPE_MAP:
                var name = params.name;
                var mapType = serie.mapType;
                for (var i = 0, l = shapeList.length; i < l; i++) {
                    if (shapeList[i].type === 'text' && shapeList[i]._mapType === mapType && shapeList[i].style._name === name) {
                        this._curTarget = shapeList[i];
                        x = this._curTarget.style.x + this._curTarget.position[0];
                        y = this._curTarget.style.y + this._curTarget.position[1];
                        break;
                    }
                }
                break;
            case ecConfig.CHART_TYPE_CHORD:
                var name = params.name;
                for (var i = 0, l = shapeList.length; i < l; i++) {
                    if (shapeList[i].type === 'sector' && ecData.get(shapeList[i], 'name') == name) {
                        this._curTarget = shapeList[i];
                        var style = this._curTarget.style;
                        var midAngle = (style.startAngle + style.endAngle) / 2 * Math.PI / 180;
                        x = this._curTarget.style.x + Math.cos(midAngle) * (style.r - 2);
                        y = this._curTarget.style.y - Math.sin(midAngle) * (style.r - 2);
                        this.zr.trigger(zrConfig.EVENT.MOUSEMOVE, {
                            zrenderX: x,
                            zrenderY: y
                        });
                        return;
                    }
                }
                break;
            case ecConfig.CHART_TYPE_FORCE:
                var name = params.name;
                for (var i = 0, l = shapeList.length; i < l; i++) {
                    if (shapeList[i].type === 'circle' && ecData.get(shapeList[i], 'name') == name) {
                        this._curTarget = shapeList[i];
                        x = this._curTarget.position[0];
                        y = this._curTarget.position[1];
                        break;
                    }
                }
                break;
            }
            if (x != null && y != null) {
                this._event = {
                    zrenderX: x,
                    zrenderY: y
                };
                this.zr.addHoverShape(this._curTarget);
                this.zr.refreshHover();
                this._showItemTrigger();
            }
        }
    },
    /**
         * 关闭，公开接口 
         */
    hideTip: function () {
        this._hide();
    },
    /**
         * 刷新
         */
    refresh: function (newOption) {
        // this._selectedMap;
        // this._defaultCssText;    // css样式缓存
        // this._needAxisTrigger;   // 坐标轴触发
        // this._curTarget;
        // this._event;
        // this._curTicket;         // 异步回调标识，用来区分多个请求
        // 缓存一些高宽数据
        this._zrHeight = this.zr.getHeight();
        this._zrWidth = this.zr.getWidth();
        if (this._lastTipShape && this._lastTipShape.tipShape.length > 0) {
            this.zr.delShape(this._lastTipShape.tipShape);
        }
        this._lastTipShape = false;
        this.shapeList.length = 2;
        this._lastDataIndex = -1;
        this._lastSeriesIndex = -1;
        this._lastItemTriggerId = -1;
        if (newOption) {
            this.option = newOption;
            this.option.tooltip = this.reformOption(this.option.tooltip);
            this.option.tooltip.textStyle = zrUtil.merge(this.option.tooltip.textStyle, this.ecTheme.textStyle);
            this._needAxisTrigger = false;
            if (this.option.tooltip.trigger === 'axis') {
                this._needAxisTrigger = true;
            }
            var series = this.option.series;
            for (var i = 0, l = series.length; i < l; i++) {
                if (this.query(series[i], 'tooltip.trigger') === 'axis') {
                    this._needAxisTrigger = true;
                    break;
                }
            }
            // this._hidingTicket;
            // this._showingTicket;
            this._showDelay = this.option.tooltip.showDelay;
            // 显示延迟
            this._hideDelay = this.option.tooltip.hideDelay;
            // 隐藏延迟
            this._defaultCssText = this._style(this.option.tooltip);
            this._setSelectedMap();
            this._axisLineWidth = this.option.tooltip.axisPointer.lineStyle.width;
            this._enterable = this.option.tooltip.enterable;
            if (!this._enterable && this._tDom.className.indexOf(zrConfig.elementClassName) < 0) {
                this._tDom.className += ' ' + zrConfig.elementClassName;
            }
        }
        if (this.showing) {
            var self = this;
            setTimeout(function () {
                self.zr.trigger(zrConfig.EVENT.MOUSEMOVE, self.zr.handler._event);
            }, 50);
        }
    },
    /**
         * 释放后实例不可用，重载基类方法
         */
    onbeforDispose: function () {
        if (this._lastTipShape && this._lastTipShape.tipShape.length > 0) {
            this.zr.delShape(this._lastTipShape.tipShape);
        }
        clearTimeout(this._hidingTicket);
        clearTimeout(this._showingTicket);
        this.zr.un(zrConfig.EVENT.MOUSEMOVE, this._onmousemove);
        this.zr.un(zrConfig.EVENT.GLOBALOUT, this._onglobalout);
        if (this.hasAppend && !!this.dom.firstChild) {
            this.dom.firstChild.removeChild(this._tDom);
        }
        this._tDom = null;
    },
    /**
         * html转码的方法
         */
    _encodeHTML: function (source) {
        return String(source).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
    }
};
zrUtil.inherits(Tooltip, Base);
require('../component').define('tooltip', Tooltip);
module.exports = Tooltip || module.exports;;